﻿#include <Windows.h>
#include <string>
#include <tchar.h>

//服务描述
#define  Description        L"自定义服务后台"
//默认服务名称
#define  DefaultServerName  L"TestService"


SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning = true;

void WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
void WINAPI ServiceCtrlHandler(DWORD Opcode);

//安装服务
BOOL InstallService();
//卸载服务
BOOL DeleteService();

//exe名称
TCHAR agrvExeName[1024] = {0};
//exe的命令行参数
TCHAR agrvCommandLine[1024] = {0};

STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;

BOOL bRet;
DWORD processActive;
TCHAR w_strDir[MAX_PATH] = {0};

TCHAR serverName[1024];
TCHAR defaultServerName[] = DefaultServerName;

void DoTask()
{
    if (!bRet)
    {
        si.dwFlags = STARTF_USESTDHANDLES;

        TCHAR szPath[1024] = {0};
        wcscat_s(szPath, 1024, agrvExeName);
        wcscat_s(szPath, 1024, L" ");

        wcscat_s(szPath,1024, agrvCommandLine);
        wcscat_s(szPath, 1024, L" ");

        bRet = CreateProcess(NULL,szPath,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,w_strDir,&si, &pi);
    }
    else 
    {
        GetExitCodeProcess(pi.hProcess, &processActive);
        if (processActive != STILL_ACTIVE) 
        {
            bRet = false;
        }
    }
}

int _tmain(int argc, TCHAR* argv[])
{
    GetModuleFileName(NULL, w_strDir, MAX_PATH);
    (_tcsrchr(w_strDir, _T('\\')))[1] = 0;

    if (argc <= 1)
    {
        printf("Usage:\n\nInstall: RunExeAsService.exe -i [程序名称] [命令行参数] [服务名称]\n\nUninstall: RunExeAsService.exe -d [服务名称]\n");
        getchar();
        return 0;
    }

    if (memcmp(argv[1], L"-i", 4) == 0)
    {
        if (argc >= 4)
        {
            lstrcpy(agrvExeName, argv[2]);
            lstrcpy(agrvCommandLine, argv[3]);
        }
        if (argc == 5)
        {
            lstrcpy(serverName, argv[4]);
        }
        else
        {
            lstrcpy(serverName, defaultServerName);
        }
        if (InstallService())
        {
            printf("服务安装成功!\n");
        }
        else
        {
            printf("服务已经安装过,或同名!\n");
        }
    }

    else if (memcmp(argv[1], L"-d", 4) == 0)
    {
        if (argc == 3)
        {
            lstrcpy(serverName, argv[2]);
        }
        else
        {
            lstrcpy(serverName, defaultServerName);
        }
        
        if (DeleteService())
        {
            printf("服务卸载成功!\n");
        }
        else
        {
            printf("找不到需要卸载的服务!\n");
        }
    }

    else if (memcmp(argv[1], L"-e", 4) == 0)
    {
        lstrcpy(agrvExeName, argv[2]);
        lstrcpy(agrvCommandLine, argv[3]);
        if (argv[4])
        {
            lstrcpy(serverName, argv[4]);
        }

        SERVICE_TABLE_ENTRY DispatchTable[] = { {serverName,ServiceMain},{NULL,NULL} };
        StartServiceCtrlDispatcher(DispatchTable);
        return 0;
    }

    else
    {
        printf("Usage:\n\nInstall: RunExeAsService.exe -i [程序名称] [命令行参数] [服务名称]\n\nUninstall: RunExeAsService.exe -d [服务名称]\n");
        getchar();
    }
    return 0;
}

void WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{ 
    m_ServiceStatus.dwServiceType = SERVICE_WIN32;
    m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    m_ServiceStatus.dwWin32ExitCode = 0;
    m_ServiceStatus.dwServiceSpecificExitCode = 0;
    m_ServiceStatus.dwCheckPoint = 0;
    m_ServiceStatus.dwWaitHint = 0;

    m_ServiceStatusHandle = RegisterServiceCtrlHandler(serverName, ServiceCtrlHandler);
    if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
    {
        return;
    }
    m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    m_ServiceStatus.dwCheckPoint = 0;
    m_ServiceStatus.dwWaitHint = 0;
    if (!SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus))
    {
        return;
    }

    bRunning = TRUE;
    while (bRunning)
    {
        //Place Your Code for processing here....   
        DoTask();
        Sleep(10000);
    }
    return;
}


void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
    switch (Opcode)
    {
    case SERVICE_CONTROL_PAUSE:
        m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
        break;

    case SERVICE_CONTROL_CONTINUE:
        m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        break;

    case SERVICE_CONTROL_STOP:
        TerminateProcess(pi.hProcess, 300);
        bRet = false;
        m_ServiceStatus.dwWin32ExitCode = 0;
        m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        m_ServiceStatus.dwCheckPoint = 0;
        m_ServiceStatus.dwWaitHint = 0;
        SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);
        bRunning = false;
        break;

    case SERVICE_CONTROL_INTERROGATE:
        break;
    }
    return;
}

BOOL InstallService()
{
    TCHAR strDir[1024];
    SC_HANDLE schSCManager, schService; 
    GetModuleFileName(NULL, strDir, 1024);
    lstrcat(strDir, L" -e ");
    lstrcat(strDir, agrvExeName);
    lstrcat(strDir, L" ");
    lstrcat(strDir, agrvCommandLine);
    lstrcat(strDir, L" ");
    lstrcat(strDir, serverName);
    lstrcat(strDir, L" ");
    schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (schSCManager == NULL)
        return false;
    LPCTSTR lpszBinaryPathName = strDir;

    schService = CreateService((struct SC_HANDLE__*)schSCManager, 
        serverName, serverName,      // service name to display  
        SERVICE_ALL_ACCESS,          // desired access  
        SERVICE_WIN32_OWN_PROCESS,   // service type  
        SERVICE_AUTO_START,          // start type  
        SERVICE_ERROR_NORMAL,        // error control type  
        lpszBinaryPathName,          // service's binary  
        NULL,                        // no load ordering group  
        NULL,                        // no tag identifier  
        NULL,                        // no dependencies  
        NULL,                        // LocalSystem account  
        NULL);                       // no password  

    if (schService == NULL)
        return false;
    SERVICE_DESCRIPTION   sdBuf;
    sdBuf.lpDescription = (LPWSTR)Description;
    ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdBuf);

    StartService(schService, 0, NULL);
    Sleep(100);

    CloseServiceHandle(schService);
    return true;
}

//执行停止服务
BOOL RunStopService(TCHAR *pServiceName)
{
    HANDLE schSCManager;
    SC_HANDLE hService;
    schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (schSCManager == NULL)
    {
        return FALSE;
    }

    hService = OpenService((struct SC_HANDLE__*)schSCManager, pServiceName, SERVICE_ALL_ACCESS);
    if (hService == NULL)
    {
        return FALSE;
    }

    SERVICE_STATUS status;
    QueryServiceStatus(hService, &status);          // 获得服务的当前状态
    if (status.dwCurrentState != SERVICE_STOPPED)   // 如果服务不处于停止状态，则将其状态设置为停止
    {
        ControlService(hService, SERVICE_CONTROL_STOP, &status);
    }
    CloseServiceHandle(hService);
    CloseHandle(schSCManager);
    return TRUE;
}


//执行删除服务
BOOL RunDeleteService(TCHAR* pServiceName)
{
    HANDLE schSCManager;
    SC_HANDLE hService;
    schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (schSCManager == NULL)  return FALSE;

    hService = OpenService((struct SC_HANDLE__*)schSCManager, pServiceName, SERVICE_ALL_ACCESS);
    if (hService == NULL)  return FALSE;

    SERVICE_STATUS status;
    QueryServiceStatus(hService, &status);  // 获得服务的当前状态

    if (::DeleteService(hService) == 0) return FALSE;
    CloseServiceHandle(hService);
    CloseHandle(schSCManager);
    return TRUE;
}

//删除服务
BOOL DeleteService()
{
    if (!RunStopService(serverName))
    {
        return FALSE;
    }

    Sleep(100);
    return RunDeleteService(serverName);
}
